#ifndef ___W25Q_APP_FLASH__
#define ___W25Q_APP_FLASH__

#include "gd32f4xx.h"
#include "gd32f4xx_libopt.h"
#include "systick.h"

/**
 * @brief Flash 存储指令定义
 */
#define FLASH_WRITE_ENABLE_CMD        0x06  /**< 启用写操作 */
#define FLASH_WRITE_DISABLE_CMD       0x04  /**< 禁用写操作 */
#define FLASH_READ_SR_CMD             0x05  /**< 读取状态寄存器 */
#define FLASH_WRITE_SR_CMD            0x01  /**< 写入状态寄存器 */
#define FLASH_READ_DATA               0x03  /**< 读取数据 */
#define FLASH_FASTREAD_DATA           0x0b  /**< 快速读取数据 */
#define FLASH_WRITE_PAGE              0x02  /**< 写入页 */
#define FLASH_ERASE_PAGE              0x81  /**< 擦除页 */
#define FLASH_ERASE_SECTOR            0x20  /**< 擦除扇区 */
#define FLASH_ERASE_BLOCK             0xd8  /**< 擦除块 */
#define FLASH_ERASE_CHIP              0xc7  /**< 擦除整个芯片 */
#define FLASH_POWER_DOWN              0xb9  /**< 进入掉电模式 */
#define FLASH_RELEASE_POWER_DOWN      0xab  /**< 释放掉电模式 */
#define FLASH_READ_DEVICE_ID          0x90  /**< 读取设备 ID */
#define FLASH_READ_JEDEC_ID           0x9f  /**< 读取 JEDEC ID */

/**
 * Flash 存储大小和结构定义
 */
#define W25Q_FLASH_SIZE    (1*1024*1024)  /**< Flash 大小：1MB */
#define PAGE_SIZE          8192           /**< 页大小：256 字节 */
#define SECTOR_SIZE        512            /**< 扇区大小：4KB */
#define BLOCK_SIZE         32             /**< 块大小：64KB */

#define PAGE_LEN           255            /**< 页长度：256 字节 */

/**
 * 用于 Flash 操作的临时缓冲区
 */
__align(4) uint8_t g_DataTmpBuffer[4096] = {0};
#define SectorBuf  g_DataTmpBuffer  /**< 用于扇区操作的缓冲区 */

/**
 * 定义 Flash 属性的结构体
 */
struct Flash_Attr {
    uint16_t flash_id;      /**< Flash ID */
    uint16_t page_size;     /**< 页大小（字节） */
    uint16_t sector_size;   /**< 扇区大小（字节） */
    uint8_t block_size;     /**< 块大小（字节） */
};

#define FALSH_TEST_ADDR    (0x100)  /**< Flash 测试地址 */

/**
 * Flash 片选宏定义
 */
#define FLASH_CS_0()  {gpio_bit_write(GPIOD, GPIO_PIN_0,RESET);delay_1ms(10);}  /**< 选择 Flash 芯片 */
#define FLASH_CS_1()  {gpio_bit_write(GPIOD, GPIO_PIN_0,SET);delay_1ms(10);}    /**< 取消选择 Flash 芯片 */

__align(4) uint16_t g_WriteReadcnt = 0;       /**< 读写计数器 */
__align(4) uint8_t g_WriteData[0x100] = {0};  /**< 写数据缓冲区 */
__align(4) uint16_t g_Count = 0;              /**< 通用计数器 */
__align(4) uint8_t g_ucPos = 0;               /**< 通用位置 */

/**
 * @brief SFLASH_ReadID - 读取 Flash 设备 ID
 * @return 设备 ID
 */
uint16_t SFLASH_ReadID(void);

/**
 * @brief Flash_WriteDisable - 禁用 Flash 写操作
 */
void Flash_WriteDisable(void);

/**
 * @brief Flash_WriteEnable - 启用 Flash 写操作
 */
void Flash_WriteEnable(void);

/**
 * @brief Flash_ReadSR - 读取 Flash 状态寄存器
 * @return 状态寄存器的值
 */
uint8_t Flash_ReadSR(void);

/**
 * @brief Flash_WaitNobusy - 等待 Flash 空闲
 */
void Flash_WaitNobusy(void);

/**
 * @brief Flash_WriteSR - 写入一个字节到 Flash 状态寄存器
 * @param _ucByte 要写入的字节
 */
void Flash_WriteSR(uint8_t _ucByte);

/**
 * @brief Flash_ErasePage - 擦除 Flash 内存中的一页
 * @param _ulPageAddr 要擦除的页地址
 */
void Flash_ErasePage(uint32_t _ulPageAddr);

/**
 * @brief Flash_EraseSector - 擦除 Flash 内存中的一个扇区
 * @param _ulSectorAddr 要擦除的扇区地址
 */
void Flash_EraseSector(uint32_t _ulSectorAddr);

/**
 * @brief Flash_EraseBlock - 擦除 Flash 内存中的一个块
 * @param _ulBlockAddr 要擦除的块地址
 */
void Flash_EraseBlock(uint32_t _ulBlockAddr);

/**
 * @brief Flash_EraseChip - 擦除整个 Flash 芯片
 */
void Flash_EraseChip(void);

/**
 * @brief Flash_ReadSomeBytes - 从 Flash 内存读取一些字节数据
 * @param ucpBuffer 存储读取数据的缓冲区
 * @param _ulReadAddr 读取的地址
 * @param _usNByte 读取的字节数
 */
void Flash_ReadSomeBytes(uint8_t *ucpBuffer, uint32_t _ulReadAddr, uint16_t _usNByte);

/**
 * @brief Flash_WritePage - 写入一页数据到 Flash 内存
 * @param ucpBuffer 存储要写入数据的缓冲区
 * @param _ulWriteAddr 写入的地址
 * @param _usNByte 写入的字节数
 */
void Flash_WritePage(uint8_t *ucpBuffer, uint32_t _ulWriteAddr, uint16_t _usNByte);

/**
 * @brief Flash_WriteNoCheck - 无检查写入数据到 Flash 内存, 需要保证FLASH数据已经被擦除成0xFF
 * @param ucpBuffer 存储要写入数据的缓冲区
 * @param _ulWriteAddr 写入的地址
 * @param _usNByte 写入的字节数
 */
void Flash_WriteNoCheck(uint8_t *ucpBuffer, uint32_t _ulWriteAddr, uint16_t _usNByte);

/**
 * @brief Flash_WriteSomeBytes - 写入一些字节数据到 Flash 内存
 * @param ucpBuffer 存储要写入数据的缓冲区
 * @param _ulWriteAddr 写入的地址
 * @param _usNByte 写入的字节数
 */
void Flash_WriteSomeBytes(uint8_t *ucpBuffer, uint32_t _ulWriteAddr, uint16_t _usNByte);

#endif	//__PRJ_STM32F10X_APP_FLASH_C__